package com.bluedot.service;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSONObject;
import com.bluedot.controller.DistributeClass;
import com.bluedot.pojo.pack.PreMappedStatement;
import com.bluedot.pojo.pack.ResultEntity;
import com.bluedot.pojo.po.*;
import com.bluedot.pojo.vo.MaterialVO;
import com.bluedot.pojo.vo.ReportVO;
import com.bluedot.pojo.vo.UserVO;
import com.bluedot.utils.FileUtils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.*;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;


public class AnalyzedataService extends DistributeClass {

    private UtilTool utilTool = new UtilTool();

    // 限制上传的最大文件类型
    private final static long fileMaxSize = 1;
    private final static Set<String> typeSet = new HashSet<String>();
    private final static String READ_ERR = "读取文件失败....";
    static {
        typeSet.add("txt");
    }

    // 构造方法调用具体业务
    public AnalyzedataService(PreMappedStatement<String> preMappedStatement) {

        super(preMappedStatement);

        String[] split = preMappedStatement.getMethodType().split("/");
        ResultEntity resultEntity = null;
        switch (split[split.length - 1]) {
            case "doadd":
                // 导入数据
                resultEntity = importAnalyzeData(preMappedStatement);
                // 返回响应结果
                getResponseQueue().add(resultEntity);
                break;
            case "querypoints":
                // 查询原始物质数据电流点位
                resultEntity = queryPoints(preMappedStatement);
                // 返回响应结果
                getResponseQueue().add(resultEntity);
                break;
            case "queryperprocess":
                // 数据预处理
                resultEntity = doPreprocessData(preMappedStatement);
                // 返回响应结果
                getResponseQueue().add(resultEntity);
                break;
            case "dowaveanalyze":
                // 波形参数分析
                resultEntity = WaveformAnalysis(preMappedStatement);
                // 返回响应结果
                getResponseQueue().add(resultEntity);
                break;
            case "avatarwaveanalyze":
                // 保存波形参数分析数据
                resultEntity = doWaveformAnalysis(preMappedStatement);
                // 返回响应结果
                getResponseQueue().add(resultEntity);
                break;
            case "domodel":
                // 数据建模
                resultEntity = doModel(preMappedStatement);
                // 返回响应结果
                getResponseQueue().add(resultEntity);
                break;
            case "docalculate":
                // 数据建模预测
                resultEntity = doModelCalculate(preMappedStatement);
                // 返回响应结果
                getResponseQueue().add(resultEntity);
                break;
            default:
                break;
        }
    }

    private ResultEntity doModelCalculate(PreMappedStatement<String> preMappedStatement) {

        String data = preMappedStatement.getData();
        JSONObject jsonObject = JSONObject.parseObject(data);
        // 实验报告Id
        String reportId = jsonObject.getString("reportId");
        // 建模预测数字
        String dataX = jsonObject.getString("dataX");
        ReportVO reportVO = new ReportVO();
        reportVO.setReportId(Integer.valueOf(reportId));
        List<Object> query = utilTool.query(new PreMappedStatement<>(UtilTool.QUERY, reportVO));
        // 获取最新的
        if(query == null || query.isEmpty()) return ResultEntity.falseWithoutData("数据预测失败！");

        ReportVO o = (ReportVO)query.get(0);
        String testEquation = o.getTestEquation();
        String[] s = testEquation.split(" ");
        if(s.length == 4){
            Double b = Double.valueOf(s[0]);
            Double k = Double.valueOf(s[2]);
            Double y = k * Double.valueOf(dataX) + b;
            return ResultEntity.successWithData(y);
        }
        return ResultEntity.falseWithoutData("数据预测失败！");
    }

    private ResultEntity doModel(PreMappedStatement<String> preMappedStatement) {

        // 数据建模分析
        /*
        * 总体逻辑：
        * 1、接收电流与浓度
        * 2、进行数据预处理
        * 3、建立线性模型
        * 4、产生实验报告
        * 5、实验报告存入数据库
        * */

        String data = preMappedStatement.getData();
        StringBuffer stringBuffer = new StringBuffer();
        JSONObject jsonObject = JSONObject.parseObject(data);
        // 预处理算法名字
        String algorithmName = jsonObject.getString("algorithmName");
        // 建模的方法
        String modelName = jsonObject.getString("modelName");
        // 物质名称
        String materialName = jsonObject.getString("materialName");
        // 实验说明
        String reportDescribe = jsonObject.getString("reportDescribe");
        // 实验报告题头
        String reportName = jsonObject.getString("reportName");
        // 参数
        List<?> datas = jsonObject.getJSONArray("datas");
        for (Object o : datas) {
            JSONObject realData = (JSONObject) o;
            // 浓度
            String materialSolubility = realData.getString("materialSolubility");
            // 电流
            String materialIp = realData.getString("materialIp");
            stringBuffer.append(materialSolubility + "," + materialIp + ";");
        }

        // 根据算法名称和用户id寻找到对应的算法
        String[] args = getAlgorithmArgs(algorithmName);
        String[] model = getAlgorithmArgs(modelName);
        // 获得算法环境、算法路径、算法参数、算法类型
        args[2] = stringBuffer.toString();


        // 调用算法
        String result = null;
        try {
            // 获取预处理完的点位，格式：“x,y;x1,y1;”
            result = modelAlgorithm(args);

            // 用这些点位开始进行模型的训练
            model[2] = result;
            // 获取线性回归的参数
            result = modelAlgorithm(model);
            String[] split = result.split(";");
            // 检验模型，获得报告
            if(split.length != 11) return ResultEntity.falseWithoutData("数据建模失败....");
            ReportDetail reportDetail = handleModel(split,model);
            // 保存到数据库中(report、reportdetail)
            Report report = new Report();
            HttpSession session = preMappedStatement.getRequest().getSession();
            UserVO user = (UserVO)session.getAttribute("user");
            /*UserVO user = new UserVO();
            user.setUserId("22080007");*/

            report.setUserId(user.getUserId());
            report.setMaterialName(materialName);
            report.setReportState(0);
            report.setReportDescribe(reportDescribe);
            report.setReportName(reportName);
            report.setAlgorithmName(algorithmName);
            report.setModelName(modelName);


            Material material = new Material();
            material.setMaterialName(materialName);

            List<Object> query1 = utilTool.query(new PreMappedStatement(UtilTool.QUERY, material));
            if(query1 == null || query1.isEmpty()) return ResultEntity.falseWithoutData("数据建模失败！");

            material = (Material) query1.get(query1.size() - 1);
            report.setMaterialId(material.getMaterialId());

            // 插入(事务)
            utilTool.insert(new PreMappedStatement(UtilTool.INSERT, report));
            List<Object> query = utilTool.query(new PreMappedStatement<>(UtilTool.QUERY, report));
            // 获取最新的
            if(query == null || query.isEmpty()) return ResultEntity.falseWithoutData("数据建模失败！");

            Report o = (Report) query.get(query.size() - 1);
            reportDetail.setReportId(o.getReportId());
            utilTool.insert(new PreMappedStatement(UtilTool.INSERT, reportDetail));


        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
            return ResultEntity.falseWithoutData(e.getMessage());
        }


        return ResultEntity.successWithoutData();

    }

    private ReportDetail handleModel(String[] split, String[] model) {

        // split : [训练方程w, 训练方程b,训练r2,训练rmse,训练mae,测试方程w, 测试方程b,测试r2,测试rmse,测试mae,测试rpd]

        double trainW = Double.valueOf(split[0]);
        double trainB = Double.valueOf(split[1]);
        double trainR2 = Double.valueOf(split[2]);
        double trainRmse = Double.valueOf(split[3]);
        double trainMae = Double.valueOf(split[4]);
        double testW = Double.valueOf(split[5]);
        double testB = Double.valueOf(split[6]);
        double testR2 = Double.valueOf(split[7]);
        double testRmse = Double.valueOf(split[8]);
        double testMae = Double.valueOf(split[9]);
        double testRpd = Double.valueOf(split[10]);


        // 指标
       /* Double w = null,b = null;
        if("线性模型".equals(model[3])){
            w = Double.valueOf(split[0]);
            b = Double.valueOf(split[1]);
        }

        // 开始验证
        String data = model[2];


        String[] split1 = data.split(";");
        int length = split1.length;
        // 电流
        Double[] ips = new Double[length];
        // 浓度
        Double[]  solubilities= new Double[length];
        for (int i = 0;i < length;i ++) {

            String[] split2 = split1[i].split(",");
            ips[i] = Double.valueOf(split2[0]);
            solubilities[i] = Double.valueOf(split2[1]);

        }

        // 测试数据与训练数据默认55分
        Double[] test = new Double[length / 2 + 1];
        Double[] excepted = new Double[length / 2 + 1];
        double yi = 0;
        for (int i = length / 2 ;i < length;i ++) {
            // 真实数据
            test[i] = solubilities[i];
            yi += solubilities[i];
            // 预测值
            excepted[i] = w * ips[i] + b;


        }

        yi /= (length / 2);
        double r2 = 0,x2 = 0 , y2 = 0,rmse = 0,mae = 0 ,x3 = 0;
        int n = 0;
        for (int i = length / 2 ;i < length;i ++,n++) {

           x2 += Math.pow(excepted[i] - test[i],2);
           y2 += Math.pow(yi - test[i],2);
           x3 += Math.abs(excepted[i] - test[i]);



        }
        // 计算决定系数
        r2 = 1 - (x2 / y2);
        // 均方根误差（RMSE）
        rmse = Math.sqrt(Math.pow(1 / n,2) * x2);
        // 平均绝对误差
        mae = x3 * (1 / n);*/


        // 生成测试
        String data = model[2];


        String[] split1 = data.split(";");
        int length = split1.length;
        // 电流
        double[] ips = new double[length];
        // 浓度
        double[]  solubilities= new double[length];
        for (int i = 0;i < length;i ++) {

            String[] split2 = split1[i].split(",");
            ips[i] = Double.valueOf(split2[0]);
            solubilities[i] = Double.valueOf(split2[1]);

        }

        StringBuffer testIp = new StringBuffer();
        StringBuffer testY = new StringBuffer();
        StringBuffer testPreY = new StringBuffer();
        StringBuffer trainIp = new StringBuffer();
        StringBuffer trainY = new StringBuffer();
        StringBuffer trainPreY = new StringBuffer();


        for (int i = 0,j = 0;i < length ;i ++) {

            if(i <= length / 2){
                trainIp.append(ips[i] + ",");
                trainY.append(solubilities[i]+",") ;
                trainPreY.append((trainW * ips[i] + trainB) + ",");

            }else{
                testIp.append(ips[i] + ",");
                testY.append(solubilities[i]+",") ;
                testPreY.append((testW * ips[j] + testB)+",");
            }
        }

        // 训练集回归方程
        String trainEquation = trainB + " + " + trainW + " x";
        // 测试集回归方恒1
        String testEquation = testB + " + " + testW + " x";


        ReportDetail reportDetail = new ReportDetail(trainMae, testMae, trainR2, trainRmse,
                testRmse, testRpd, testR2, trainY.toString(), trainIp.toString(),
                trainPreY.toString(), testY.toString(), testIp.toString(), testPreY.toString(),
                trainEquation, testEquation);


        return reportDetail;

    }


    private String[] getAlgorithmArgs(String algorithmName){
        // 根据算法名称和用户id寻找到对应的算法
        Algorithm algorithm = new Algorithm();
        algorithm.setAlgorithm_name(algorithmName);
        HttpSession session = preMappedStatement.getRequest().getSession();
        UserVO user = (UserVO)session.getAttribute("user");

  /*      UserVO user = new UserVO();
        user.setUserId("22080007");*/
        algorithm.setUser_id(user.getUserId());
        List<Object> query = utilTool.query(new PreMappedStatement<>(UtilTool.QUERY,algorithm));
        if(query == null){
            // 说明用户没有该算法
            algorithm.setUser_id(null);
        }
        query = utilTool.query(new PreMappedStatement<>(UtilTool.QUERY,algorithm));
        if(query == null || query.isEmpty()) return null;

        algorithm =(Algorithm) query.get(0);
        // 获取算法执行地址
        String algorithm_url = algorithm.getAlgorithm_url();
        // 文件所属类型
        String algorithm_exe = algorithm.getAlgorithm_exe();
        // 算法类型
        String algorithm_type = algorithm.getAlgorithm_type();

        // 获得算法环境、算法路径、算法参数、算法类型
        String[] args = new String[] { algorithm_exe, algorithm_url,null};
        return args;

    }

    private String modelAlgorithm(String[] args) throws IOException, InterruptedException {
        // 数据预处理算法
        String way = args[0];
        Process proc = null;
        String arg = args[2];
        String[] split = arg.split(";");
        if("python".equals(way)){
            // 执行py文件
            proc = Runtime.getRuntime().exec(args);
        }else if("c++".equals(way)){
            // 根据命令调用 c++
            proc = Runtime.getRuntime().exec(args[1]);
            // 终端输入参数 (输入y的坐标组)
            OutputStream outputStream = proc.getOutputStream();
            PrintWriter outputWriter = new PrintWriter(outputStream, true);
            // 添加参数
            addParameters(outputWriter,split);
            outputWriter.close();

        }else if("matlab".equals(way)){
            // 调用 matlab 算法

        }

        // 获取结果（算法处理后的浓度和电流）
        BufferedReader in = new BufferedReader(new InputStreamReader(proc.getInputStream()));
        String line = null;

        StringBuffer preResult = new StringBuffer();
        while ((line = in.readLine()) != null) {
            preResult.append(line + ";");
        }
        // 关闭流文件
        in.close();
        proc.waitFor();

        return preResult.toString();


    }

    private ResultEntity doWaveformAnalysis(PreMappedStatement<String> preMappedStatement) {

        // 把vo信息存入到物质详情表中
        String data = preMappedStatement.getData();
        MaterialVO materialVO = JSONObject.parseObject(data, MaterialVO.class);

        MaterialDetail materialDetail = new MaterialDetail();
        BeanUtil.copyProperties(materialVO,materialDetail);
        materialDetail.setMaterialState(2);
        // 查询需要
        MaterialDetail materialDetail1 = new MaterialDetail();
        materialDetail1.setMaterialState(materialDetail.getMaterialState());
        materialDetail1.setMaterialId(materialDetail.getMaterialId());

        // 保存前先要查询一遍，数据库没有波形参数分析状态数据就插入，有的话就进行更新
        List<Object> query1 = utilTool.query(new PreMappedStatement(UtilTool.QUERY, materialDetail1));
        if(query1 == null){
            // 插入新数据（id置为空）
            materialDetail.setMaterialSpecificId(null);
            utilTool.insert(new PreMappedStatement(UtilTool.INSERT, materialDetail));
        }else{
            materialDetail.setMaterialSpecificId(((MaterialDetail)query1.get(0)).getMaterialSpecificId());
            utilTool.update(new PreMappedStatement(UtilTool.UPDATE, materialDetail));
        }

        return ResultEntity.successWithoutData();
    }

    private ResultEntity WaveformAnalysis(PreMappedStatement<String> preMappedStatement){

        // 波形参数分析
        /*
         * 主要流程：根据传入的左点位坐标、右点位坐标计算出两点间直线的距离，再代入最高点的横坐标，得出ip
         * */
        String data = preMappedStatement.getData();
        MaterialVO materialVO = JSONObject.parseObject(data, MaterialVO.class);

        List<Point> points1 = getPoints(materialVO);
        // 最高点坐标
        Point point = points1.get(0);
        double max = Double.parseDouble(point.getYPoint());
        for (int i = 0;i < points1.size(); i++ ) {
            double v = Double.parseDouble(points1.get(i).getYPoint());
            if(max < v){
                max = v;
                point = points1.get(i);
            }
        }

        String left = materialVO.getLeftPoint();
        String right = materialVO.getRightPoint();
        Point leftPoint = getPoint(left);
        Point rightPoint = getPoint(right);


        // 计算斜率
        double k = (Double.valueOf(leftPoint.getYPoint()) - Double.valueOf(rightPoint.getYPoint()) )/ (Double.valueOf(leftPoint.getXPoint()) - Double.valueOf(rightPoint.getXPoint()));
        // 计算 b = y - kx;
        double y = Double.valueOf(leftPoint.getYPoint());
        double x = Double.valueOf(leftPoint.getXPoint());
        double b = y - k * x;

        double y1 = k * Double.valueOf(point.getXPoint()) + b;
        double Ip = Double.valueOf(point.getYPoint()) - y1;
        double Ep = Double.valueOf(point.getXPoint());

        List<Double> list = new ArrayList<>();
        list.add(Ip);
        list.add(Ep);
        materialVO.setMaterialIp(Ip);
        materialVO.setMaterialEp(Ep);
        // 两种方案：1、返回ip和ep ，前端设置值 2、后端直接返回对象,前端重新渲染
        //return ResultEntity.successWithData(list);
        return ResultEntity.successWithData(materialVO);

    }


    private Point getPoint(String po){

        // 0.708,-2.848e-6
        String[] split = po.split(",");
        return new Point(split[0],split[1]);

    }


    private ResultEntity doPreprocessData(PreMappedStatement<String> preMappedStatement) {

        // 获取 json 数据
        String data = preMappedStatement.getData();
        JSONObject jsonObject = JSONObject.parseObject(data);
        // 获取需要进行预处理的数据集合
        List<?> pointlist = jsonObject.getJSONArray("points");

        StringBuffer stringBuffer = new StringBuffer();
        for (Object point : pointlist) {
            JSONObject pointJson = (JSONObject)point;
            stringBuffer.append(pointJson.getString("xPoint") + ",");
            stringBuffer.append(pointJson.getString("yPoint") + ";");
        }
        String points = stringBuffer.toString();
        // 获取预处理的算法名称
        String algorithmName = jsonObject.getString("algorithmName");
        // 获取物质数据 id
        String materialId = jsonObject.getString("materialId");

        // 根据算法名称和用户id寻找到对应的算法
        Algorithm algorithm = new Algorithm();
        algorithm.setAlgorithm_name(algorithmName);
        HttpSession session = preMappedStatement.getRequest().getSession();
        UserVO user = (UserVO)session.getAttribute("user");
       /* UserVO user = new UserVO();
        user.setUserId("22080001");*/
        algorithm.setUser_id(user.getUserId());
        List<Object> query = utilTool.query(new PreMappedStatement<>(UtilTool.QUERY,algorithm));
        if(query == null){
            // 说明用户没有该算法
            algorithm.setUser_id(null);
        }
        query = utilTool.query(new PreMappedStatement<>(UtilTool.QUERY,algorithm));
        if(query == null || query.isEmpty()) return ResultEntity.falseWithoutData("未查询到相应算法！");
        algorithm =(Algorithm) query.get(0);
        // 获取算法执行地址
        String algorithm_url = algorithm.getAlgorithm_url();
        // 文件所属类型
        String algorithm_exe = algorithm.getAlgorithm_exe();
        // 算法环境、算法路径、算法参数
        String[] args = new String[] { algorithm_exe, algorithm_url, points};



        // 清空内容
        stringBuffer.delete(0, stringBuffer.length());

        String result = null;
        try {
            result = execAlgorithm(args);
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
            return ResultEntity.falseWithoutData(e.getMessage());
        }
        // 处理完进行插入数据

        // 插入 ip 和 ep
        MaterialDetail old_materialDetail = new MaterialDetail();
        old_materialDetail.setMaterialId(Integer.valueOf(materialId));
        List<Object> query2 = utilTool.query(new PreMappedStatement(UtilTool.QUERY, old_materialDetail));
        if(query2 == null || query2.isEmpty()) return ResultEntity.falseWithoutData("预处理失败！");

        old_materialDetail = (MaterialDetail)query2.get(0);


        // 先要查询数据是否有预处理状态，有的话就更新（重复预处理），没有的话就插入预处理数据记录
        MaterialDetail materialDetail = new MaterialDetail(1, result, Integer.valueOf(materialId), algorithm.getAlgorithm_id(), algorithm.getAlgorithm_name());
        materialDetail.setMaterialIp(old_materialDetail.getMaterialIp());
        materialDetail.setMaterialEp(old_materialDetail.getMaterialEp());

        List<Object> query1 = utilTool.query(new PreMappedStatement(UtilTool.QUERY, materialDetail));
        if(query1 == null){
            utilTool.insert(new PreMappedStatement(UtilTool.INSERT, materialDetail));
        }else{
            materialDetail.setMaterialSpecificId(((MaterialDetail)query1.get(0)).getMaterialSpecificId());
            // 更新预处理结果
            utilTool.update(new PreMappedStatement(UtilTool.UPDATE, materialDetail));
        }


        // 查询返回预处理后的数据
        MaterialVO materialVO = new MaterialVO();
        materialVO.setMaterialState(1);
        materialVO.setMaterialId(materialDetail.getMaterialId());


        // 返回算法执行结果
        return doQueryPoints(materialVO);


    }

    private String execAlgorithm(String[] args) throws IOException, InterruptedException {

        // 数据预处理算法
        StringBuffer stringBuffer = new StringBuffer();
        String way = args[0];
        Process proc = null;
        String arg = args[2];
        List<String> result = new ArrayList<>();
        String[] split = arg.split(";");

        if("python".equals(way)){
            // 执行py文件
            proc = Runtime.getRuntime().exec(args[0] +args[1]);
        }else if("c++".equals(way)){
            // 根据命令调用 c++
            proc = Runtime.getRuntime().exec(args[1]);
        }else if("matlab".equals(way)){
            // 调用 matlab 算法
        }

        // 终端输入参数 (输入y的坐标组)
        OutputStream outputStream = proc.getOutputStream();
        PrintWriter outputWriter = new PrintWriter(outputStream, true);
        // 添加参数
        addParameters(outputWriter,split,result);
        outputWriter.close();

        // 获取结果（算法处理后的 y 坐标）
        BufferedReader in = new BufferedReader(new InputStreamReader(proc.getInputStream()));
        String line = null;
        int i = 0;
        while ((line = in.readLine()) != null && i < result.size()) {
            String s = result.get(i++);
            stringBuffer.append(s + "," + line + ";");
        }
        // 关闭流文件
        in.close();
        proc.waitFor();
        // 需要返回 x,y;
        return stringBuffer.toString();

    }

    private void addParameters(PrintWriter outputWriter,String[] split,List<String> result){
        outputWriter.print(split.length);
        for (String s : split) {
            String[] split1 = s.split(",");
            result.add(split1[0]);
            outputWriter.print(split1[1]);

        }
    }

    private void addParameters(PrintWriter outputWriter,String[] split){
        outputWriter.print(split.length);
        for (String s : split) {
            String[] split1 = s.split(",");
            outputWriter.print(split1[1]);

        }
    }

    private ResultEntity queryPoints(PreMappedStatement<String> preMappedStatement) {

        String data = preMappedStatement.getData();
        // 物质id和物质状态有值
        MaterialVO materialVO = JSONObject.parseObject(data, MaterialVO.class);
        return doQueryPoints(materialVO);


    }

    private List<Point> getPoints(MaterialVO materialVO1) {

        ArrayList<Point> points1 = new ArrayList<>();


        String points = materialVO1.getMaterialPoints();
        String[] split = points.split(";");
        for (String s : split) {
            String[] split1 = s.split(",");
            Point point = new Point(split1[0].replace(" ", ""), split1[1].replace(" ", ""));
            points1.add(point);
        }


        return points1;
    }

    private ResultEntity doQueryPoints(MaterialVO materialVO) {

        MaterialVO materialVO1 = null;
        // 查找视图
        List<Object> query = utilTool.query(new PreMappedStatement<>(UtilTool.QUERY, materialVO));
        if(query == null){
            return ResultEntity.falseWithoutData("查询数据失败....");
        }
        materialVO1 = (MaterialVO)query.get(0);
        List<Point> points = getPoints(materialVO1);
        materialVO1.setPoints(points);

        if(materialVO.getMaterialState() == 1){
            // 为1说明要进行波形参数分析，还要查询原始状态数据
            // 查询原始数据
            materialVO.setMaterialState(0);
            List<Object> queryOrigin = utilTool.query(new PreMappedStatement<>(UtilTool.QUERY, materialVO));
            if(queryOrigin == null){
                return ResultEntity.falseWithoutData("查询数据失败....");
            }
            MaterialVO originMaterialVO = (MaterialVO)queryOrigin.get(0);
            List<Point> originPoints = getPoints(originMaterialVO);
            materialVO1.setOriginPoint(originPoints);
        }

        // 方法
        return ResultEntity.successWithData(materialVO1);

    }



    private ResultEntity importAnalyzeData(PreMappedStatement<String> preMappedStatement) {

        try {
            // 获取文件流
            InputStream file = preMappedStatement.getFile();
            ResultEntity resultEntity = checkDataFormat(file);// Ep ip points
            if("FALSE".equals(resultEntity.getResult())){
                return resultEntity;
            }
            String[] points =(String[]) resultEntity.getData();
            if (points.length != 3) {
                return ResultEntity.falseWithoutData(AnalyzedataService.READ_ERR);
            }


            // 根据 json 数据得到实体类
            HttpServletRequest request = preMappedStatement.getRequest();
            HttpSession session = request.getSession();
            UserVO user = (UserVO) session.getAttribute("user");
//            UserVO user = new UserVO();
//            user.setUserId("22080001");

            // 从request表单中获取对象
            MaterialVO materialVO = packageMaterialVO(request);
            materialVO.setMaterialPoints(points[2]);
            materialVO.setUserId(user.getUserId());
            // 插入实体类(数据、数据详情)
            Material material = new Material();
            MaterialDetail materialDetail = new MaterialDetail();

            BeanUtil.copyProperties(materialVO, material);
            // 如果前端转递的时间不为空，那么进行设置
            LocalDateTime createTime = materialVO.getCreateTime();
            material.setCreateTime(createTime);

            // 通过物质类型获取物质类型的id
            MaterialType materialType = new MaterialType();
            materialType.setMaterialTypeName(materialVO.getMaterialType());
            List<Object> query1 = utilTool.query(new PreMappedStatement<>(UtilTool.QUERY, materialType));
            if(query1!=null) material.setMaterialTypeId(((MaterialType)query1.get(0)).getMaterialTypeId());

            utilTool.insert(new PreMappedStatement(UtilTool.INSERT, material));
            List<Object> query = utilTool.query(new PreMappedStatement<>(UtilTool.QUERY, material));
            if(query == null || query.isEmpty()) return ResultEntity.falseWithoutData("操作失败！");

            // 获取最新的
            Material o = (Material) query.get(query.size() - 1);
            materialDetail.setMaterialId(o.getMaterialId());
            // 状态是正常状态
            materialDetail.setMaterialState(0);
            materialDetail.setMaterialPoints(points[2]);

            points[0] = points[0] == "" ? "0.0" : points[0];
            points[1] = points[1] == "" ? "0.0" : points[1];
            materialDetail.setMaterialEp(Double.valueOf(points[0]));
            materialDetail.setMaterialIp(Double.valueOf(points[1]));
            utilTool.insert(new PreMappedStatement(UtilTool.INSERT, materialDetail));
            // 返回最新的vo数据
            MaterialVO materialVO1 = new MaterialVO();
            materialVO1.setMaterialId(o.getMaterialId());
            materialVO1.setMaterialState(0);
            return doQueryPoints(materialVO1);

        } catch (Exception e) {
            e.printStackTrace();
            return ResultEntity.falseWithoutData(e.getMessage());
        }

    }

    private ResultEntity checkDataFormat(InputStream file) throws IOException {
        FileInputStream fileInputStream = null;

        if (file instanceof FileInputStream) {
            fileInputStream = (FileInputStream) file;
        }
        if (fileInputStream == null){
            return ResultEntity.falseWithoutData(AnalyzedataService.READ_ERR);
        }
        // 检验文件格式以及大小
        ResultEntity resultEntity = FileUtils.checkFile(fileInputStream, fileMaxSize, typeSet);
        if("FALSE".equals(resultEntity.getResult())){
            return resultEntity;
        }
        int available = fileInputStream.available();

        // 设置缓冲值，控制读写的次数
        byte[] bytes = new byte[available];
        int result;
        StringBuffer stringBuffer = new StringBuffer();

        while ((result = fileInputStream.read(bytes)) != -1) {
            // 每一次写入时都会覆盖原有的byte数组，长度为 result
            stringBuffer.append(new String(bytes, 0, result));
        }

        // Ep = 0.900V
        int i1 = stringBuffer.indexOf("Ep = ");
        String Ep = "";
        String ip = "";
        if(i1 != -1){
            // 说明，不存在
            int i2 = stringBuffer.indexOf("ip = ");
            int i3 = stringBuffer.indexOf("Ap");
            Ep = stringBuffer.substring(i1 + "Ep = ".length() , i2 - 5);
            ip = stringBuffer.substring(i2 + "ip = ".length(), i3 -3);
        }


        int index = stringBuffer.indexOf("Potential/V, Current/A");
        String substring = stringBuffer.substring(index + "Potential/V, Current/A".length()+4 );
        // 替换分隔符
        String points = substring.replaceAll("\r\n", ";");
        String[] result1 = new String[]{Ep,ip,points};
        return ResultEntity.successWithData(result1);
    }

    public static String bytesToHexString(byte[] src) {
        StringBuilder stringBuilder = new StringBuilder();
        if (src == null || src.length <= 0) {
            return null;
        }
        for (int i = 0; i < src.length; i++) {
            int v = src[i] & 0xFF;
            String hv = Integer.toHexString(v);
            if (hv.length() < 2) {
                stringBuilder.append(0);
            }
            stringBuilder.append(hv);
        }
        return stringBuilder.toString();
    }





    private MaterialVO packageMaterialVO(HttpServletRequest request) throws Exception {
        request.setCharacterEncoding("UTF-8");

        String materialType = request.getParameter("materialType");
        MaterialType materialType1 = new MaterialType();
        materialType1.setMaterialTypeName(materialType);
        // 根据物质类型，查询出物质类型 id
        List<Object> query = utilTool.query(new PreMappedStatement<>(UtilTool.QUERY,materialType1));
        if(query == null){
            // 说明用户没有该物质类型
            throw new Exception("物质类型不存在！");
        }
        MaterialType o = (MaterialType)query.get(0);
        Integer materialTypeId = o.getMaterialTypeId();
        //Integer materialTypeId = Integer.valueOf(request.getParameter("materialTypeId"));
        String materialName = request.getParameter("materialName");
        Double materialSolubility = Double.valueOf(request.getParameter("materialSolubility"));
        String createTime = request.getParameter("createTime");
        String bufferSolution =request.getParameter("bufferSolution") ;
        String materialRemarks = request.getParameter("materialRemarks");
        LocalDateTime date = null;
        if (createTime != null && createTime.length() != 0) {
            DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
            date = LocalDateTime.parse(createTime, fmt);

        }
        MaterialVO materialVO = new MaterialVO(materialType, materialTypeId, materialName, materialSolubility, date, bufferSolution, materialRemarks);
        return materialVO;
    }
}



